from dataclasses import asdict
from typing import Optional, Union

from httpx import RequestError
from wazuh.core.engine.base import APPLICATION_JSON, BaseModule, convert_enums
from wazuh.core.engine.models.base import ErrorResponse
from wazuh.core.engine.models.vulnerability import ScanRequest, ScanResponse
from wazuh.core.exception import WazuhEngineError


class VulnerabilityModule(BaseModule):
    """Vulnerability module used to request vulnerability scans to the Engine."""

    MODULE = 'vulnerability'

    async def send_scan_request(self, scan_request: ScanRequest) -> Optional[Union[ScanResponse, ErrorResponse]]:
        """Send a vulnerability scan request to the engine.

        Parameters
        ----------
        scan_request : ScanRequest
            Vulnerability scan request.

        Returns
        -------
        Optional[Union[ScanResponse, ErrorResponse]]
            Vulnerability scan result, error response or None if the response is empty.
        """
        try:
            response = await self._client.post(
                url=f'{self.API_URL}/{self.MODULE}/scan',
                json=asdict(scan_request, dict_factory=convert_enums),
                headers={
                    'Accept': APPLICATION_JSON,
                    'Content-Type': APPLICATION_JSON,
                },
            )

            if response.status_code != 200:
                return ErrorResponse(**response.json())

            vulnerabilities = response.json()
            if vulnerabilities is None:
                return

            return ScanResponse(vulnerabilities=vulnerabilities)
        except RequestError as exc:
            raise WazuhEngineError(2803, extra_message=str(exc))
